home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 February
/
EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso
/
enigma
/
earcd
/
varie
/
uae-0_64.lha
/
uae-0.6.4
/
src
/
os.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-03
|
16KB
|
714 lines
/*
* UAE - The Un*x Amiga Emulator
*
* OS specific functions
*
* (c) 1995 Bernd Schmidt
* (c) 1996 Marcus Sundberg
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "os.h"
#include "events.h"
#ifndef DONT_WANT_SOUND
static void sample16_handler(void);
static void sample8_handler(void);
#endif
int joystickpresent = 0;
#ifdef HAVE_LINUX_JOYSTICK_H
static int js0;
struct JS_DATA_TYPE jscal;
void read_joystick(UWORD *dir, int *button)
{
static int minx = MAXINT, maxx = MININT,
miny = MAXINT, maxy = MININT;
int left = 0, right = 0, top = 0, bot = 0;
struct JS_DATA_TYPE buffer;
int len;
*dir = 0;
*button = 0;
if (!joystickpresent)
return;
len = read(js0, &buffer, sizeof(buffer));
if (len != sizeof(buffer))
return;
if (buffer.x < minx) minx = buffer.x;
if (buffer.y < miny) miny = buffer.y;
if (buffer.x > maxx) maxx = buffer.x;
if (buffer.y > maxy) maxy = buffer.y;
if (buffer.x < (minx + (maxx-minx)/3))
left = 1;
else if (buffer.x > (minx + 2*(maxx-minx)/3))
right = 1;
if (buffer.y < (miny + (maxy-miny)/3))
top = 1;
else if (buffer.y > (miny + 2*(maxy-miny)/3))
bot = 1;
if (left) top = !top;
if (right) bot = !bot;
*dir = bot | (right << 1) | (top << 8) | (left << 9);
*button = (buffer.buttons & 3) != 0;
}
void init_joystick(void)
{
js0 = open("/dev/js0", O_RDONLY);
if (js0 < 0)
return;
joystickpresent = 1;
}
void close_joystick(void)
{
if (joystickpresent)
close(js0);
}
#elif defined(__DOS__)
void read_joystick(UWORD *dir, int *button)
{
static int minx = MAXINT, maxx = MININT,
miny = MAXINT, maxy = MININT;
int left = 0, right = 0, top = 0, bot = 0;
char JoyPort;
int laps, JoyX, JoyY;
*dir = 0;
*button = 0;
if (!joystickpresent)
return;
JoyX = 0;
JoyY = 0;
laps = 0;
__asm__ __volatile__("cli");
outportb(0x201, 0xff);
do {
JoyPort = inportb(0x201);
JoyX = JoyX + (JoyPort & 1);
JoyY = JoyY + ((JoyPort & 2) >> 1);
laps++;
} while(((JoyPort & 3) != 0) && (laps != 65535));
__asm__ __volatile__("sti");
if (JoyX < minx) minx = JoyX;
if (JoyY < miny) miny = JoyY;
if (JoyX > maxx) maxx = JoyX;
if (JoyY > maxy) maxy = JoyY;
if (JoyX < (minx + (maxx-minx)/3))
left = 1;
else if (JoyX > (minx + 2*(maxx-minx)/3))
right = 1;
if (JoyY < (miny + (maxy-miny)/3))
top = 1;
else if (JoyY > (miny + 2*(maxy-miny)/3))
bot = 1;
if (left) top = !top;
if (right) bot = !bot;
*dir = bot | (right << 1) | (top << 8) | (left << 9);
*button = ((~JoyPort) & 48) != 0;
}
void init_joystick(void)
{
int laps = 0;
char JoyPort;
__asm__ __volatile__("cli");
outportb(0x201, 0xff);
do {
JoyPort = inportb(0x201);
laps++;
} while(((JoyPort & 3) != 0) && (laps != 65535));
__asm__ __volatile__("sti");
if (laps != 65535)
joystickpresent = 1;
}
void close_joystick(void)
{
}
#else
void read_joystick(UWORD *dir, int *button)
{
*dir = 0;
*button = 0;
}
void init_joystick(void)
{
}
void close_joystick(void)
{
}
#endif
int sound_available = 0;
static long count = 0;
struct audio_channel_data audio_channel[4];
/* The buffer is too large... */
static UWORD buffer[44100], *bufpt;
static ULONG data;
int sound_table[256][64];
static int smplcnt = 0;
static int dspbits = 16, freq_divisor = 1;
static int sndbufsize;
static void init_sound_table16(void)
{
int i,j;
for (i = 0; i < 256; i++)
for (j = 0; j < 64; j++)
sound_table[i][j] = j * (BYTE)i;
}
static void init_sound_table8(void)
{
int i,j;
for (i = 0; i < 256; i++)
for (j = 0; j < 64; j++)
sound_table[i][j] = (j * (BYTE)i) / 256;
}
static int exact_log2(int v)
{
int l = 0;
while ((v >>= 1) != 0)
l++;
return l;
}
#ifdef LINUX_SOUND
#include <sys/ioctl.h>
#include <sys/soundcard.h>
static int sfd;
static int have_sound;
int init_sound (void)
{
int tmp;
int rate;
unsigned long formats;
sfd = open ("/dev/dsp", O_WRONLY);
have_sound = !(sfd < 0);
if (!have_sound) {
return 0;
}
ioctl (sfd, SNDCTL_DSP_GETFMTS, &formats);
if (sound_desired_bsiz < 128 || sound_desired_bsiz > 16384) {
fprintf(stderr, "Sound buffer size %d out of range.\n", sound_desired_bsiz);
sound_desired_bsiz = 8192;
}
tmp = 0x00040000 + exact_log2(sound_desired_bsiz);
ioctl (sfd, SNDCTL_DSP_SETFRAGMENT, &tmp);
ioctl (sfd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
dspbits = sound_desired_bits;
ioctl(sfd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
ioctl(sfd, SOUND_PCM_READ_BITS, &dspbits);
if (dspbits != sound_desired_bits) {
fprintf(stderr, "Can't use sound with %d bits\n", sound_desired_bits);
return 0;
}
tmp = 0;
ioctl(sfd, SNDCTL_DSP_STEREO, &tmp);
rate = sound_desired_freq;
ioctl(sfd, SNDCTL_DSP_SPEED, &rate);
ioctl(sfd, SOUND_PCM_READ_RATE, &rate);
/* Some soundcards have a bit of tolerance here. */
if (rate < sound_desired_freq * 90 / 100 || rate > sound_desired_freq * 110 / 100) {
fprintf(stderr, "Can't use sound with desired frequency %d\n", sound_desired_freq);
return 0;
}
eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
if (dspbits == 16) {
/* Will this break horribly on Linux/Alpha? Possible... */
if (!(formats & AFMT_S16_LE))
return 0;
init_sound_table16 ();
eventtab[ev_sample].handler = sample16_handler;
} else {
if (!(formats & AFMT_U8))
return 0;
init_sound_table8 ();
eventtab[ev_sample].handler = sample8_handler;
}
sound_available = 1;
printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n",
dspbits, rate, sndbufsize);
bufpt = buffer;
smplcnt = 0;
return 1;
}
static void flush_sound_buffer(void)
{
write(sfd, buffer, sndbufsize);
bufpt = buffer;
}
#elif defined(AF_SOUND)
#include <AF/AFlib.h>
static AFAudioConn *aud;
static AC ac;
static long aftime;
static int rate;
static int have_sound;
int init_sound (void)
{
AFSetACAttributes attributes;
AFDeviceDescriptor *aDev;
int device;
aud = AFOpenAudioConn(NULL);
have_sound = !(aud == NULL);
if (!have_sound) {
return 0;
}
for(device = 0; device < ANumberOfAudioDevices(aud); device++) {
aDev = AAudioDeviceDescriptor(aud, device);
rate = aDev->playSampleFreq;
sndbufsize = (rate / 8) * 4;
if(aDev->inputsFromPhone == 0
&& aDev->outputsToPhone == 0
&& aDev->playNchannels == 1)
break;
}
if (device == ANumberOfAudioDevices(aud)) {
return 0;
}
dspbits = 16;
attributes.type = LIN16;
ac = AFCreateAC(aud, device, ACEncodingType, &attributes);
aftime = AFGetTime(ac);
init_sound_table16 ();
eventtab[ev_sample].handler = sample16_handler;
eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
bufpt = buffer;
smplcnt = 0;
sound_available = 1;
printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
return 1;
}
static void flush_sound_buffer(void)
{
long size = (char *)bufpt - (char *)buffer;
if (AFGetTime(ac) > aftime)
aftime = AFGetTime(ac);
AFPlaySamples(ac, aftime, size, (unsigned char*) buffer);
aftime += size / 2;
bufpt = buffer;
}
#elif defined(__mac__)
#include <Sound.h>
static SndChannelPtr newChannel;
static ExtSoundHeader theSndBuffer;
static SndCommand theCmd;
/* The buffer is too large... */
static UWORD buffer0[44100], buffer1[44100], *bufpt;
static int have_sound;
static int nextbuf=0;
static Boolean sFlag=true;
int init_sound (void)
{
if (SndNewChannel(&newChannel, sampledSynth, initMono, NULL))
return 0;
sndbufsize = 44100;
init_sound_table8 ();
smplcnt = 0;
bufpt = buffer0;
sound_available = 1;
return 1;
}
static void flush_sound_buffer(void)
{
bufpt = buffer0;
theSndBuffer.samplePtr = (Ptr)buffer0;
theSndBuffer.numChannels = 1;
theSndBuffer.sampleRate = 0xac440000;
theSndBuffer.encode = extSH;
theSndBuffer.numFrames = sndbufsize;
theSndBuffer.sampleSize = 8;
theCmd.param1 = 0;
theCmd.param2 = (long)&theSndBuffer;
theCmd.cmd = bufferCmd;
SndDoCommand(newChannel, &theCmd, false);
}
#elif defined(__DOS__)
#include "dos-sb.h"
void (*SND_Write)(void *buf, unsigned long size); // Pointer to function that plays data on card
int dos_dsprate = 1; // 0 for 44100 - 1 for 22050
int dos_dspbits = 16;
int init_sound (void)
{
int rate;
dspbits = sound_desired_bits;
rate = sound_desired_freq;
if (rate == 22050)
dos_dsprate = 1;
else if (rate == 44100)
dos_dsprate = 0;
else {
fprintf(stderr, "Can't use sample rate %d!\n", rate);
return 0;
}
if (SB_DetectInitSound(&dspbits, &dos_dsprate, &sndbufsize));
else if (0/*OTHER_CARD_DETECT_ROUTINE*/);
else
return 0;
eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
if (dspbits == 16) {
init_sound_table16 ();
eventtab[ev_sample].handler = sample16_handler;
} else {
init_sound_table8 ();
eventtab[ev_sample].handler = sample8_handler;
}
sound_available = 1;
printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n",
dspbits, rate, sndbufsize);
bufpt = buffer;
smplcnt = 0;
return 1;
}
static void flush_sound_buffer(void)
{
SND_Write(buffer, sndbufsize);
bufpt = buffer;
}
#elif defined(SOLARIS_SOUND)
#include <sys/audioio.h>
static int sfd;
static int have_sound;
int init_sound (void)
{
int rate;
struct audio_info sfd_info;
sfd = open("/dev/audio", O_WRONLY);
have_sound = !(sfd <0);
if (!have_sound) {
return 0;
}
rate = sound_desired_freq;
dspbits = sound_desired_bits;
AUDIO_INITINFO(&sfd_info); /* 44100Hz, mono, 16Bit, linear */
sfd_info.play.sample_rate = rate;
sfd_info.play.channels = 1;
sfd_info.play.precision = dspbits;
sfd_info.play.encoding = AUDIO_ENCODING_LINEAR;
if (ioctl(sfd, AUDIO_SETINFO, &sfd_info)) {
fprintf(stderr, "Can't use sample rate %d with %d bits!\n", rate, bits);
return 0;
}
eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
if (dspbits == 16) {
init_sound_table16 ();
eventtab[ev_sample].handler = sample16_handler;
} else {
init_sound_table8 ();
eventtab[ev_sample].handler = sample8_handler;
}
bufpt = buffer;
smplcnt = 0;
sound_available = 1;
sndbufsize = dspbits/8 * rate;
printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
return 1;
}
static void flush_sound_buffer(void)
{
write(sfd, buffer, sndbufsize);
bufpt = buffer;
}
#else
int init_sound (void)
{
produce_sound = 0;
return 1;
}
static void flush_sound_buffer(void)
{
}
#endif
void AUDxDAT(int nr, UWORD v)
{
#ifndef DONT_WANT_SOUND
struct audio_channel_data *cdp = audio_channel + nr;
cdp->dat = v;
if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
cdp->state = 2;
INTREQ(0x8000 | (0x80 << nr));
/* data_written = 2 ???? */
eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
eventtab[ev_aud0 + nr].oldcycles = cycles;
eventtab[ev_aud0 + nr].active = 1;
events_schedule();
}
#endif
}
#ifndef DONT_WANT_SOUND
static void sample16_handler(void)
{
int nr;
ULONG data = 0;
eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
eventtab[ev_sample].oldcycles = cycles;
if (produce_sound < 2)
return;
for (nr = 0; nr < 4; nr++) {
if (!(adkcon & (0x11 << nr)))
data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol];
}
*bufpt++ = data;
if ((char *)bufpt - (char *)buffer >= sndbufsize) {
flush_sound_buffer();
}
}
static void sample8_handler(void)
{
int nr;
ULONG data = 0;
unsigned char *bp = (unsigned char *)bufpt;
eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
eventtab[ev_sample].oldcycles = cycles;
if (produce_sound < 2)
return;
for (nr = 0; nr < 4; nr++) {
if (!(adkcon & (0x11 << nr)))
data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol];
}
*bp++ = data + 128;
bufpt = (UWORD *)bp;
if ((char *)bufpt - (char *)buffer >= sndbufsize) {
flush_sound_buffer();
}
}
static void audio_handler(int nr)
{
struct audio_channel_data *cdp = audio_channel + nr;
switch (cdp->state) {
case 0:
fprintf(stderr, "Bug in sound code\n");
break;
case 1:
/* We come here at the first hsync after DMA was turned on. */
eventtab[ev_aud0 + nr].evtime += maxhpos;
eventtab[ev_aud0 + nr].oldcycles += maxhpos;
cdp->state = 5;
INTREQ(0x8000 | (0x80 << nr));
if (cdp->wlen != 1)
cdp->wlen--;
cdp->nextdat = chipmem_bank.wget(cdp->pt);
cdp->pt += 2;
break;
case 5:
/* We come here at the second hsync after DMA was turned on. */
if (produce_sound == 0)
cdp->per = 65535;
eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
eventtab[ev_aud0 + nr].oldcycles = cycles;
cdp->dat = cdp->nextdat;
cdp->current_sample = (UBYTE)(cdp->dat >> 8);
cdp->state = 2;
{
int audav = adkcon & (1 << nr);
int audap = adkcon & (16 << nr);
int napnav = (!audav && !audap) || audav;
if (napnav)
cdp->data_written = 2;
}
break;
case 2:
/* We come here when a 2->3 transition occurs */
if (produce_sound == 0)
cdp->per = 65535;
cdp->current_sample = (UBYTE)(cdp->dat & 0xFF);
eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
eventtab[ev_aud0 + nr].oldcycles = cycles;
cdp->state = 3;
/* Period attachment? */
if (adkcon & (0x10 << nr)) {
if (cdp->intreq2 && cdp->dmaen)
INTREQ(0x8000 | (0x80 << nr));
cdp->intreq2 = 0;
cdp->dat = cdp->nextdat;
if (cdp->dmaen)
cdp->data_written = 2;
if (nr < 3) {
if (cdp->dat == 0)
(cdp+1)->per = 65535;
else if (cdp->dat < maxhpos/2 && produce_sound < 3)
(cdp+1)->per = maxhpos/2;
else
(cdp+1)->per = cdp->dat;
}
}
break;
case 3:
/* We come here when a 3->2 transition occurs */
if (produce_sound == 0)
cdp->per = 65535;
eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
eventtab[ev_aud0 + nr].oldcycles = cycles;
if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
cdp->state = 0;
cdp->current_sample = 0;
eventtab[ev_aud0 + nr].active = 0;
break;
} else {
int audav = adkcon & (1 << nr);
int audap = adkcon & (16 << nr);
int napnav = (!audav && !audap) || audav;
cdp->state = 2;
if ((cdp->intreq2 && cdp->dmaen && napnav)
|| (napnav && !cdp->dmaen))
INTREQ(0x8000 | (0x80 << nr));
cdp->intreq2 = 0;
cdp->dat = cdp->nextdat;
cdp->current_sample = (UBYTE)(cdp->dat >> 8);
if (cdp->dmaen && napnav)
cdp->data_written = 2;
/* Volume attachment? */
if (audav) {
if (nr < 3)
(cdp+1)->vol = cdp->dat;
}
}
break;
default:
cdp->state = 0;
eventtab[ev_aud0 + nr].active = 0;
break;
}
}
void aud0_handler(void)
{
audio_handler(0);
}
void aud1_handler(void)
{
audio_handler(1);
}
void aud2_handler(void)
{
audio_handler(2);
}
void aud3_handler(void)
{
audio_handler(3);
}
#endif